export default class Table {
    constructor (db, name, descriptor) {
        this.descriptor = descriptor
        this.db = db
        this.create()
        this.joins = []
        this.wheres = []
    }
    alias (al) {
        this.al = al
        return this
    }
    fields (fields) {
        this.fields_str = fields
        return this
    }
    where (...where) {
        this.wheres.push(where)
        return this
    }
    join (...join) {
        this.joins.push({
            table:join[0],
            on:join[1],
            relation:join[2]?join[2]:'INNER'
        })
        return this
    }
    order (order) {
        this.order_str = order
        return this
    }
    group (group) {
        this.group_str = group
        return this
    }
    limit (limit) {
        this.limit_str = limit
        return this
    }
    page(page, pageSize) {
        let select_sql = 'SELECT ' + (this.fields_str?this.fields_str:' * ')
        + ' FROM ' + this.descriptor.name + ' ' +  (this.al?this.al:'') + ' '
        let join_sql = ''
        if (this.joins) {
            for (let join of this.joins) {
                join_sql += join.relation + ' JOIN ' + join.table + ' ON ' + join.on
            }
        }
        select_sql += join_sql
        select_sql += ' WHERE 1 = 1 ' + this.get_where(this.wheres)
        select_sql += this.order_str?' ORDER BY ' + this.order_str:''
        select_sql += this.group_str?' GROUP BY ' + this.group_str:''
        select_sql += ' LIMIT ' + pageSize + ' OFFSET ' + (page - 1) * pageSize
        return new Promise((resolve,reject) => {
            this.db.transaction((tx) =>{
                tx.executeSql(select_sql,[],(transaction, results)=>{
                    resolve(results.rows)
                },(transaction, errmsg) => {
                    reject(errmsg)
                })
            })
        })
    }
    buildSql () {
        let select_sql = 'SELECT ' + (this.fields_str?this.fields_str:' * ')
            + ' FROM ' + this.descriptor.name +  ' ' +  (this.al?this.al:'') + ' '
        let join_sql = ''
        if (this.joins) {
            for (let join of this.joins) {
                join_sql += join.relation + ' JOIN ' + join.table + ' ON ' + join.on
            }
        }
        select_sql += join_sql
        select_sql += ' WHERE 1 = 1 ' + this.get_where(this.wheres)
        select_sql += this.order_str?' ORDER BY ' + this.order_str:''
        select_sql += this.group_str?' GROUP BY ' + this.group_str:''
        select_sql += this.limit_str?' LIMIT ' + this.limit_str:''
        return '(' + select_sql + ')'
    }
    select () {
        let select_sql = 'SELECT ' + (this.fields_str?this.fields_str:' * ')
                    + ' FROM ' + this.descriptor.name + ' ' +  (this.al?this.al:'') + ' '
        let join_sql = ''
        if (this.joins) {
            for (let join of this.joins) {
                join_sql += join.relation + ' JOIN ' + join.table + ' ON ' + join.on
            }
        }
        select_sql += join_sql
        select_sql += ' WHERE 1 = 1 ' + this.get_where(this.wheres)
        select_sql += this.order_str?' ORDER BY ' + this.order_str:''
        select_sql += this.group_str?' GROUP BY ' + this.group_str:''
        select_sql += this.limit_str?' LIMIT ' + this.limit_str:''
        return new Promise((resolve,reject) => {
            this.db.transaction((tx) =>{
                tx.executeSql(select_sql,[],(transaction, results)=>{
                    resolve(results.rows)
                },(transaction, errmsg) => {
                    reject(errmsg)
                })
            })
        })
    }
    delete () {
        let delete_sql = 'DELETE FROM ' + this.descriptor.name
                + ' ' + this.get_where(this.wheres)
        return new Promise( (resolve, reject) => {
            this.db.transaction((tx) => {
                tx.executeSql(delete_sql, [],
                    (tx, results) =>{
                        resolve(results.rows)
                    },
                    (tx, errmsg) => {
                        reject(errmsg)
                    })

            })
        })
    }
    find () {
        let select_sql = 'SELECT ' + (this.fields_str?this.fields_str:' * ')
        + ' FROM ' + this.descriptor.name + ' ' +  (this.al?this.al:'') + ' '
        let join_sql = ''
        if (this.joins) {
            for (let join of this.joins) {
                join_sql += join.relation + ' JOIN ' + join.table + ' ON ' + join.on
            }
        }
        select_sql += join_sql
        select_sql += ' WHERE 1 = 1 ' + this.get_where(this.wheres)
        select_sql += this.order_str?' ORDER BY ' + this.order_str:''
        select_sql += this.group_str?' GROUP BY ' + this.group_str:''
        select_sql += ' LIMIT  1'
        console.log(select_sql)
        return new Promise((resolve,reject) => {
            this.db.transaction((tx) =>{
                tx.executeSql(select_sql,[],(transaction, results)=>{
                    resolve(results.rows)
                },(transaction, errmsg) => {
                    reject(errmsg)
                })
            })
        })
    }
    insert(obj) {
        let { sql, values} = this.get_insert_statement(obj)
        return new Promise((resolve,reject) => {
            this.db.transaction((tx) =>{
                tx.executeSql(sql, values, (transaction, results)=>{
                    resolve(results.rows)
                },(transaction, errmsg) => {
                    reject(errmsg)
                })
            })
        })
    }
    update (obj) {
        let update_sql = this.get_update_statement(obj)
        return new Promise((resolve, reject) => {
            this.db.transaction((tx) => {
                tx.executeSql(update_sql, [], (transaction, results) => {
                    resolve(results.rows)
                }, (transaction, errmsg) => {
                    reject(errmsg)
                })
            })
        })
    }
    create () {
        let statement = this.get_create_statement()
        console.log(statement)
        this.db.transaction((tx) => {
            tx.executeSql(statement,[],()=>{},(transaction,msg)=>console.log(msg))
        })
    }
    get_create_statement () {
        let ret = 'CREATE TABLE IF NOT EXISTS ' + this.descriptor.name + '( '
        for (let field in this.descriptor.fields) {
            ret += field + ' ' + this.descriptor.fields[field] + ','
        }
        ret = ret.substr(0, ret.length - 1)
        return ret + ')'
    }
    get_update_statement (obj, wheres) {
        let ret = 'UPDATE ' + this.descriptor.name + 'SET '
        for (let field in obj) {
            ret += field + ' = \'' + obj[field] + '\','
        }
        ret = ret.substr(0, ret.length - 1)
        ret +=  ' WHERE 1 = 1 '
        ret += this.get_where(wheres)
        return ret
    }
    get_insert_statement (obj) {
        let sql = 'INSERT INTO ' + this.descriptor.name,
            field_arr = [],
            tmp = [],
            values = []
        for (let key in obj) {
            field_arr.push(key)
            tmp.push('?')
            values.push(obj[key])
        }
        sql += '( ' + field_arr.join(',') + ') VALUES (' + tmp.join(',') + ')'
        return { sql, values }
    }

    get_where (wheres) {
        let ret = ''
        for (let where of wheres) {
            if (!where instanceof Array) {
                ret += ' AND ' + where
            }else {
                if (where[0].trim() == 'and' || where[0].trim() == 'or') {
                    if (where.length == 2) {
                        ret += ' ' + where[0] + ' ' + where[1]
                    }else if (where.length == 3) {
                        ret += ' ' + where[0] + ' ' + where[1] + ' = \'' + where[2] + '\''
                    }else if (where.length == 4) {
                        ret += ' ' + where[0] + ' ' + where[1] + ' ' + where[2] + ' ' + '\'' + where[3] + '\''
                    }
                }else if (where.length == 2) {
                    ret += ' AND ' + where[0] + ' = \'' + where[1] + '\''
                }else if (where.length == 3) {
                    ret += 'AND ' + where[0] + ' ' + where[1] + ' \'' + where[2] + '\''
                }
            }
        }
        return ret
    }


}